/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.azon.left.hand;

import java.awt.Point;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

/**
 *
 * @author Mahdan Ahmad F A
 */
public class FilledWetLeftHand extends WetLeftHand{
  
    @Override
    public String[] doWetLeftHand(int[][] matrix) {
        ArrayList<String> array = new ArrayList<>();
        
        int[] start = detectorBlack(matrix);
        
        int iteration = 0;
        
        while (((start[0] != -28) && (start[1] != -28)) /*&& (iteration < 3)*/) {
            array.add(createAChainCode(matrix, start[0], start[1]));
            
            //flood_matrix = matrix;
            
            matrix = floodFill(matrix, start[0], start[1], 1);
            
            //matrix = flood_matrix;
            start   = detectorBlack(matrix);
            
            iteration++;
        } // 
        
        String[] chain_codes = array.toArray(new String[array.size()]);
        
        return chain_codes;
    }
       
    private String createAChainCode(int[][] matrix, int startX, int startY) {
        
        String chain_code = "";
        
        String north        = "12369874";
        String northEast    = "23698741";
        String east         = "36987412";
        String southEast    = "69874123";
        String south        = "98741236";
        String southWest    = "87412369";
        String west         = "74123698";
        String northWest    = "41236987";
        
        String precedence = southEast;
        
        int direction;
        
        int nextX = -99;
        int nextY = -99;
        
        int iteration = 0;

        while ((!(startX == nextX) || !(startY == nextY))/* && (iteration < 100)*/) {
            if (chain_code.isEmpty()) {
                direction = 0;
                nextX = startX;
                nextY = startY;   
            } else {
                direction = chain_code.charAt(chain_code.length() - 1) - 48;
            }
            
            //System.out.println("************************************************");
            //System.out.println("Iterasi ke-" + (iteration + 1) + " = " + nextX + " " + nextY);
            
            switch(direction) {
                case 1:
                    precedence = northWest;
                    break;
                case 2:
                    precedence = north;
                    break;
                case 3:
                    precedence = northEast;
                    break;
                case 4:
                    precedence = west;
                    break;
                case 6:
                    precedence = east;
                    break;
                case 7:
                    precedence = southWest;
                    break;
                case 8:
                    precedence = south;
                    break;
                case 9:
                    precedence = southEast;
                    break;
            }

            int[] next = new int[2];
            for (int i = 0; i < precedence.length(); i++) {
                if(isAvailable(matrix, nextX, nextY, (precedence.charAt(i) - 48))) {
                    chain_code += precedence.charAt(i);
                    next = getNext(nextX, nextY, (precedence.charAt(i) - 48));

                    break;
                }
            }
            
            nextX = next[0];
            nextY = next[1];
            iteration++;
        } 
        
        //System.out.println("Chain code = " + chain_code);
        
        return startX + "X" + startY + "Y" + chain_code;
        
    }
    
    private int[][] floodFill(int[][] matrix, int posX, int posY, int targetColor) {

        boolean[][] painted = new boolean[matrix.length][matrix[0].length];
        
        for (int m = 0; m < matrix.length; m++) {
            for (int n = 0; n < matrix[0].length; n++) {
                painted[m][n] = matrix[m][n] == targetColor;
            }
        }
        
        Queue<Point> queue = new LinkedList<>();
        queue.add(new Point(posX, posY));
        painted[posX][posY] = true;
        
        
        while (!queue.isEmpty()) {
            Point pos = queue.remove();
            
            //System.out.println("NOW!!" + pos.toString());
            
            if(!(matrix[pos.x][pos.y] == targetColor)) {
                matrix[pos.x][pos.y] = targetColor;
            }
            
            if(!(matrix[pos.x+1][pos.y] == targetColor) && !(painted[pos.x+1][pos.y])) {
                painted[pos.x+1][pos.y] = true;
                queue.add(new Point(pos.x+1, pos.y));
            }
            if(!(matrix[pos.x-1][pos.y] == targetColor) && !(painted[pos.x-1][pos.y])) {
                painted[pos.x-1][pos.y] = true;
                queue.add(new Point(pos.x-1, pos.y));
            }
            if(!(matrix[pos.x][pos.y+1] == targetColor) && !(painted[pos.x][pos.y+1])) {
                painted[pos.x][pos.y+1] = true;
                queue.add(new Point(pos.x, pos.y+1));
            }
            if(!(matrix[pos.x][pos.y-1] == targetColor) && !(painted[pos.x][pos.y-1])) {
                painted[pos.x][pos.y-1] = true;
                queue.add(new Point(pos.x, pos.y-1));
            }
        }
        
        return matrix;
    }
    
    private boolean isAvailable(int[][] matrix, int startX, int startY, int direction ) {
        
        int[] position = getNext(startX, startY, direction);
        
        int posX = position[0];
        int posY = position[1];
                
        int maxX = matrix.length - 1;
        int maxY = matrix[0].length - 1;
        
        switch(direction) {
            case 1:
                //System.out.print("Nilai matrik di posisi " + direction + "(" + posX + "," + posY + ")" + " = " + matrix[posX][posY]);
                if (startX == 0) {
                    return false;
                } else {
                    if ((matrix[posX + 1][posY] == 1) && (matrix[posX][posY] == 0)) {
                        return true;
                    }
                }
                break;
            case 2:
                //System.out.print("Nilai matrik di posisi " + direction + "(" + posX + "," + posY + ")" + " = " + matrix[posX][posY]);
                if (startX == 0) {
                    if (startY == 0) {
                        return false;
                    } else if (matrix[posX][posY] == 0) {
                        return true;
                    }
                } else {
                    if ((matrix[posX][posY - 1] == 1) && (matrix[posX][posY] == 0)) {
                        return true;
                    }
                }
                break;
            case 3:
                //System.out.print("Nilai matrik di posisi " + direction + "(" + posX + "," + posY + ")" + " = " + matrix[posX][posY]);
                if (startY == 0) {
                    return false;
                } else {
                    if ((matrix[posX][posY - 1] == 1) && (matrix[posX][posY] == 0)) {
                        return true;
                    }
                }
                break;
            case 4:
                //System.out.print("Nilai matrik di posisi " + direction + "(" + posX + "," + posY + ")" + " = " + matrix[posX][posY]);
                if (startY == maxY) {
                    if (startX == 0) {
                        return false;
                    } else if (matrix[posX][posY] == 1) {
                        return true;
                    }
                } else {
                    if ((matrix[posX + 1][posY] == 1) && (matrix[posX][posY] == 0)) {
                        return true;
                    }
                }
                break;
            case 6:
                //System.out.print("Nilai matrik di posisi " + direction + "(" + posX + "," + posY + ")" + " = " + matrix[posX][posY]);
                if (startY == 0) {
                    if (startX == maxX) {
                        return false;
                    } else if (matrix[posX][posY] == 1) {
                        return true;
                    }
                } else {
                    if ((matrix[posX - 1][posY] == 1) && (matrix[posX][posY] == 0)) {
                        return true;
                    }
                }
                break;
            case 7:
                //System.out.print("Nilai matrik di posisi " + direction + "(" + posX + "," + posY + ")" + " = " + matrix[posX][posY]);
                if (startX == maxX) {
                    return false;
                } else {
                    if ((matrix[posX][posY + 1] == 1) && (matrix[posX][posY] == 0)) {
                        return true;
                    }
                }
                break;
            case 8:
                //System.out.print("Nilai matrik di posisi " + direction + "(" + posX + "," + posY + ")" + " = " + matrix[posX][posY]);
                if (startX == maxX) {
                    if (startY == maxY) {
                        return false;
                    } else if (matrix[posX][posY] == 1) {
                        return true;
                    }
                } else {
                    if ((matrix[posX][posY + 1] == 1) && (matrix[posX][posY] == 0)) {
                        return true;
                    }
                }
                break;
            case 9:
                //System.out.print("Nilai matrik di posisi " + direction + "(" + posX + "," + posY + ")" + " = " + matrix[posX][posY]);
                if (startY == maxY) {
                    return false;
                } else {
                    if ((matrix[posX - 1][posY] == 1) && (matrix[posX][posY] == 0)) {
                        return true;
                    }
                }
                break;
        }
        
        return false;
    }

}
